/*
 * DogeInsertFrame.java
 *
 * Created on 15 luglio 2007, 13.02
 */

package dogeUI;

import dogeCore.*;
import dogeScan.*;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.io.IOException;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;

/**
 *
 * @author  daniele
 */
public class DogeInsertFrame extends javax.swing.JPanel implements Observer {
    
    /**
     * Creates new form DogeInsertFrame
     */
    public DogeInsertFrame(DogeCore core) {
        this.core=core;
        //get subjects
        this.subjects=getSubjects();
        initComponents();
        initSubjectCombos();
        //selects null element for fromCombo, toCombo and documentTypeCombo
        documentTypeCombo.setSelectedIndex(-1);
        fromCombo.setSelectedIndex(-1);
        toCombo.setSelectedIndex(-1);
        //shows or hides department field according to user's department
        setDepartmentCombo();
        //verify dates (to show notifications)
        checkDates();
        hideNotify();
        //give focus to the first button in the frame
        documentButton.grabFocus();
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        popup = new javax.swing.JPopupMenu() {
            public void setVisible(boolean b) {
                Boolean isCanceled = (Boolean) getClientProperty("JPopupMenu.firePopupMenuCanceled");
                if (b || (!b && dateSelected) || ((isCanceled != null) && !b && isCanceled.booleanValue())) {
                    super.setVisible(b);
                }
            }
        };
        jScrollPane1 = new javax.swing.JScrollPane();
        insertPanel = new javax.swing.JPanel();
        expiresLabel = new javax.swing.JLabel();
        creatorLabel = new javax.swing.JLabel();
        fromErrorLabel = new javax.swing.JLabel();
        documentLabel = new javax.swing.JLabel();
        creatorCombo = new javax.swing.JComboBox(getCreators());
        toErrorLabel = new javax.swing.JLabel();
        toLabel = new javax.swing.JLabel();
        toNewButton = new javax.swing.JButton();
        dateErrorLabel = new javax.swing.JLabel();
        documentButton = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        descriptionText = new javax.swing.JTextArea();
        dateLabel = new javax.swing.JLabel();
        expiresErrorLabel = new javax.swing.JLabel();
        descriptionLabel = new javax.swing.JLabel();
        documentTypeCombo = new javax.swing.JComboBox(getDocumentTypes());
        documentTypeErrorLabel = new javax.swing.JLabel();
        fromNewButton = new javax.swing.JButton();
        fromLabel = new javax.swing.JLabel();
        documentErrorLabel = new javax.swing.JLabel();
        documentTypeLabel = new javax.swing.JLabel();
        buttonsPanel = new javax.swing.JPanel();
        confirmButton = new javax.swing.JButton();
        documentStatusLabel = new javax.swing.JLabel();
        departmentLabel = new javax.swing.JLabel();
        departmentCombo = new javax.swing.JComboBox(getDepartments());
        departmentErrorLabel = new javax.swing.JLabel();
        dateField = new javax.swing.JTextField();
        expiresField = new javax.swing.JTextField();
        dateCalendarButton = new javax.swing.JButton();
        expiresCalendarButton = new javax.swing.JButton();
        notifyLabel = new javax.swing.JLabel();

        setLayout(new java.awt.BorderLayout());

        setBorder(javax.swing.BorderFactory.createEtchedBorder());
        jScrollPane1.setBorder(null);
        insertPanel.setLayout(new java.awt.GridBagLayout());

        expiresLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        expiresLabel.setLabelFor(expiresField);
        expiresLabel.setText("Valido fino al:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 9;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
        insertPanel.add(expiresLabel, gridBagConstraints);

        creatorLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        creatorLabel.setLabelFor(documentTypeCombo);
        creatorLabel.setText("Creato da:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
        insertPanel.add(creatorLabel, gridBagConstraints);

        fromErrorLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        fromErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
        fromErrorLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        fromErrorLabel.setText("dato non inserito / soggetto inconsistente");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 10, 0);
        insertPanel.add(fromErrorLabel, gridBagConstraints);

        documentLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        documentLabel.setLabelFor(documentButton);
        documentLabel.setText("Documento:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
        insertPanel.add(documentLabel, gridBagConstraints);

        creatorCombo.setFont(new java.awt.Font("Dialog", 1, 14));
        creatorCombo.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                creatorComboFocusLost(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(creatorCombo, gridBagConstraints);

        toErrorLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        toErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
        toErrorLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        toErrorLabel.setText("dato non inserito / soggetto inconsistente");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 6;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 10, 0);
        insertPanel.add(toErrorLabel, gridBagConstraints);

        toLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        toLabel.setText("Diretto a:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
        insertPanel.add(toLabel, gridBagConstraints);

        toNewButton.setFont(new java.awt.Font("Dialog", 1, 14));
        toNewButton.setText("Nuovo...");
        toNewButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                toNewButtonActionPerformed(evt);
            }
        });
        toNewButton.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                toNewButtonFocusLost(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(toNewButton, gridBagConstraints);

        dateErrorLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        dateErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
        dateErrorLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        dateErrorLabel.setText("data non valida / data non inserita");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 8;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 10, 0);
        insertPanel.add(dateErrorLabel, gridBagConstraints);

        documentButton.setFont(new java.awt.Font("Dialog", 1, 14));
        documentButton.setText("Acquisisci...");
        documentButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                documentButtonActionPerformed(evt);
            }
        });
        documentButton.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                documentButtonFocusLost(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(documentButton, gridBagConstraints);

        descriptionText.setFont(new java.awt.Font("Dialog", 0, 14));
        descriptionText.setLineWrap(true);
        descriptionText.setRows(5);
        descriptionText.setWrapStyleWord(true);
        descriptionText.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                descriptionTextFocusLost(evt);
            }
        });
        descriptionText.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                descriptionTextKeyPressed(evt);
            }
        });

        jScrollPane2.setViewportView(descriptionText);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 15;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(jScrollPane2, gridBagConstraints);

        dateLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        dateLabel.setLabelFor(dateField);
        dateLabel.setText("Data documento:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 7;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
        insertPanel.add(dateLabel, gridBagConstraints);

        expiresErrorLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        expiresErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
        expiresErrorLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        expiresErrorLabel.setText("data non valida");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 10;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 0);
        insertPanel.add(expiresErrorLabel, gridBagConstraints);

        descriptionLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        descriptionLabel.setLabelFor(descriptionText);
        descriptionLabel.setText("Descrizione:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 15;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
        insertPanel.add(descriptionLabel, gridBagConstraints);

        documentTypeCombo.setFont(new java.awt.Font("Dialog", 1, 14));
        documentTypeCombo.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                documentTypeComboItemStateChanged(evt);
            }
        });
        documentTypeCombo.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                documentTypeComboFocusLost(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 11;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(documentTypeCombo, gridBagConstraints);

        documentTypeErrorLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        documentTypeErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
        documentTypeErrorLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        documentTypeErrorLabel.setText("dato non inserito");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 12;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 10, 0);
        insertPanel.add(documentTypeErrorLabel, gridBagConstraints);

        fromNewButton.setFont(new java.awt.Font("Dialog", 1, 14));
        fromNewButton.setText("Nuovo...");
        fromNewButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                fromNewButtonActionPerformed(evt);
            }
        });
        fromNewButton.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                fromNewButtonFocusLost(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(fromNewButton, gridBagConstraints);

        fromLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        fromLabel.setText("Proveniente da:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
        insertPanel.add(fromLabel, gridBagConstraints);

        documentErrorLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        documentErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
        documentErrorLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        documentErrorLabel.setText("<html>\n<center>\nnessun documento inserito:<br>\ncliccare su <i>Acquisisci</i> per inserire un nuovo documento\n</center>\n</html>");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 10, 0);
        insertPanel.add(documentErrorLabel, gridBagConstraints);

        documentTypeLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        documentTypeLabel.setLabelFor(documentTypeCombo);
        documentTypeLabel.setText("Tipologia di documento:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 11;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
        insertPanel.add(documentTypeLabel, gridBagConstraints);

        confirmButton.setFont(new java.awt.Font("Dialog", 1, 18));
        confirmButton.setText("Inserisci");
        confirmButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                confirmButtonActionPerformed(evt);
            }
        });

        buttonsPanel.add(confirmButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 16;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 0);
        insertPanel.add(buttonsPanel, gridBagConstraints);

        documentStatusLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        documentStatusLabel.setText("non inserito");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(documentStatusLabel, gridBagConstraints);

        departmentLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        departmentLabel.setLabelFor(documentTypeCombo);
        departmentLabel.setText("Settore di competenza:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 13;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
        insertPanel.add(departmentLabel, gridBagConstraints);

        departmentCombo.setFont(new java.awt.Font("Dialog", 1, 14));
        departmentCombo.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                departmentComboItemStateChanged(evt);
            }
        });
        departmentCombo.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                departmentComboFocusLost(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 13;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(departmentCombo, gridBagConstraints);

        departmentErrorLabel.setFont(new java.awt.Font("Dialog", 1, 14));
        departmentErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
        departmentErrorLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        departmentErrorLabel.setText("dato non inserito");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 14;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 10, 0);
        insertPanel.add(departmentErrorLabel, gridBagConstraints);

        dateField.setFont(new java.awt.Font("Dialog", 0, 14));
        dateField.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                dateFieldFocusLost(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 7;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(dateField, gridBagConstraints);

        expiresField.setFont(new java.awt.Font("Dialog", 0, 14));
        expiresField.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                expiresFieldFocusLost(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 9;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(expiresField, gridBagConstraints);

        dateCalendarButton.setFont(new java.awt.Font("Dialog", 1, 14));
        dateCalendarButton.setText("Calendario...");
        dateCalendarButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dateCalendarButtonActionPerformed(evt);
            }
        });
        dateCalendarButton.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                dateCalendarButtonFocusLost(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 7;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(dateCalendarButton, gridBagConstraints);

        expiresCalendarButton.setFont(new java.awt.Font("Dialog", 1, 14));
        expiresCalendarButton.setText("Calendario...");
        expiresCalendarButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                expiresCalendarButtonActionPerformed(evt);
            }
        });
        expiresCalendarButton.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                expiresCalendarButtonFocusLost(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 9;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        insertPanel.add(expiresCalendarButton, gridBagConstraints);

        jScrollPane1.setViewportView(insertPanel);

        add(jScrollPane1, java.awt.BorderLayout.CENTER);

        notifyLabel.setBackground(new java.awt.Color(255, 255, 204));
        notifyLabel.setFont(new java.awt.Font("Dialog", 1, 18));
        notifyLabel.setForeground(new java.awt.Color(0, 0, 0));
        notifyLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/dogeUI/images/messagebox_info.gif")));
        notifyLabel.setText("[notifica varia ed eventuale...]");
        notifyLabel.setOpaque(true);
        add(notifyLabel, java.awt.BorderLayout.NORTH);

    }// </editor-fold>//GEN-END:initComponents

    private void expiresCalendarButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_expiresCalendarButtonActionPerformed
        showCalendar(expiresField,expiresCalendarButton);
    }//GEN-LAST:event_expiresCalendarButtonActionPerformed

    private void dateCalendarButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dateCalendarButtonActionPerformed
        showCalendar(dateField,dateCalendarButton);
    }//GEN-LAST:event_dateCalendarButtonActionPerformed

    private void expiresCalendarButtonFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_expiresCalendarButtonFocusLost
        hideNotify();
    }//GEN-LAST:event_expiresCalendarButtonFocusLost

    private void expiresFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_expiresFieldFocusLost
        hideNotify();
        checkDates();
    }//GEN-LAST:event_expiresFieldFocusLost

    private void dateCalendarButtonFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_dateCalendarButtonFocusLost
        hideNotify();
    }//GEN-LAST:event_dateCalendarButtonFocusLost

    private void dateFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_dateFieldFocusLost
        hideNotify();
        checkDates();
    }//GEN-LAST:event_dateFieldFocusLost

    private void descriptionTextKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_descriptionTextKeyPressed
        //overrides standard JTextArea behaviour and uses TAB and SHIFT+TAB to focus the next or the previous widget (and not to type a \t in the box)
        if(evt.getKeyCode() == KeyEvent.VK_TAB) {
            //if shift modifier is pressed...
            if (evt.getModifiers() == KeyEvent.SHIFT_MASK){
                //do not forward the event to JTextArea
                evt.consume();
                //...give focus to previous component
                documentTypeCombo.requestFocus();
            } else {
                //do not forward the event to JTextArea
                evt.consume();
                //give focus to the following component
                fromCombo.requestFocus();
            }
        }
    }//GEN-LAST:event_descriptionTextKeyPressed

    private void fromComboFocusLost(java.awt.event.FocusEvent evt) {                                       
        hideNotify();
    }                                      
    
    private void toComboFocusLost(java.awt.event.FocusEvent evt) {                                       
        hideNotify();
    }                                      
    
    private void creatorComboFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_creatorComboFocusLost
        hideNotify();
    }//GEN-LAST:event_creatorComboFocusLost

    private void departmentComboFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_departmentComboFocusLost
        hideNotify();
    }//GEN-LAST:event_departmentComboFocusLost

    private void descriptionTextFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_descriptionTextFocusLost
        hideNotify();
    }//GEN-LAST:event_descriptionTextFocusLost

    private void documentTypeComboFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_documentTypeComboFocusLost
        hideNotify();
    }//GEN-LAST:event_documentTypeComboFocusLost

    private void documentButtonFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_documentButtonFocusLost
        hideNotify();
    }//GEN-LAST:event_documentButtonFocusLost

    private void confirmButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_confirmButtonActionPerformed
        insertRecord();
    }//GEN-LAST:event_confirmButtonActionPerformed

    private void departmentComboItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_departmentComboItemStateChanged
        //if no (valid) item is selected...
        if (departmentCombo.getSelectedIndex()==-1){
            //...show per-field notification
            //departmentCombo.setForeground(Color.RED);
            departmentErrorLabel.setText("dato non inserito: selezionare un settore di appartenenza per il documento");
            departmentErrorLabel.setVisible(true);
        } else {
            //...else hide it
            //departmentCombo.setForeground(new Color(51,51,51));
            departmentErrorLabel.setVisible(false);            
        }

    }//GEN-LAST:event_departmentComboItemStateChanged

    private void documentTypeComboItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_documentTypeComboItemStateChanged
        //if no (valid) item is selected...
        if (documentTypeCombo.getSelectedIndex()==-1){
            //...show per-field notification
            //documentTypeCombo.setForeground(Color.RED);
            documentTypeErrorLabel.setText("dato non inserito: selezionare una tipologia di documento");
            documentTypeErrorLabel.setVisible(true);
        } else {
            //...else hide it
            //documentTypeCombo.setForeground(new Color(51,51,51));
            documentTypeErrorLabel.setVisible(false);            
        }
    }//GEN-LAST:event_documentTypeComboItemStateChanged

    private void fromComboItemStateChanged(java.awt.event.ItemEvent evt) {                                           
        //if no (valid) item is selected...
        if (fromCombo.getSelectedIndex()==-1){
            //...show per-field notification
            //fromCombo.setForeground(Color.RED);
            fromErrorLabel.setText("dato non inserito: selezionare un soggetto o inserirne uno nuovo");
            fromErrorLabel.setVisible(true);
        } else if (toCombo.getSelectedIndex()!=-1){
            //...else hide it
            //fromCombo.setForeground(new Color(51,51,51));
            notifyFromToNotValid(fromToNotValid());            
        } else {
            fromErrorLabel.setVisible(false);
        }
    }                                          
    
    private void toComboItemStateChanged(java.awt.event.ItemEvent evt) {                                         
        //if no (valid) item is selected...
        if (toCombo.getSelectedIndex()==-1){
            //...show per-field notification
            //toCombo.setForeground(Color.RED);
            toErrorLabel.setText("dato non inserito: selezionare un soggetto o inserirne uno nuovo");
            toErrorLabel.setVisible(true);
        } else if (fromCombo.getSelectedIndex()!= -1){
            //...else hide it
            //toCombo.setForeground(new Color(51,51,51));
            notifyFromToNotValid(fromToNotValid());
        } else {
            toErrorLabel.setVisible(false);
        }
    }                                        

    private void toNewButtonFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_toNewButtonFocusLost
        hideNotify();
    }//GEN-LAST:event_toNewButtonFocusLost

    private void fromNewButtonFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_fromNewButtonFocusLost
        hideNotify();
    }//GEN-LAST:event_fromNewButtonFocusLost

    private void documentButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_documentButtonActionPerformed
        scanDocument();
    }//GEN-LAST:event_documentButtonActionPerformed

    private void toNewButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_toNewButtonActionPerformed
        addNewSubject(toCombo);
    }//GEN-LAST:event_toNewButtonActionPerformed

    private void fromNewButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fromNewButtonActionPerformed
        addNewSubject(fromCombo);
    }//GEN-LAST:event_fromNewButtonActionPerformed

    private void calendarPropertyChange(com.toedter.calendar.JCalendar calendar,PropertyChangeEvent evt){
        changeDate();
    }

    /** get document types */
    private Vector getDocumentTypes() {
        try {
            //get data from database...
            Vector documentTypes=core.getDocumentTypes();
            return documentTypes;
        } catch (Exception ex) {
            javax.swing.JOptionPane.showMessageDialog(this,"Si è verificato un errore accedendo al database.\nContattare l'amministratore di sistema.\n\nIl dettaglio dell'errore è:\n"+ex.getLocalizedMessage(),"Errore nell'accesso alla base di dati",javax.swing.JOptionPane.ERROR_MESSAGE);
            return null;
        }
    }
    
    /** get subjects */
    private Vector getSubjects() {
        try {
            //get data from database...
            Vector subjects=core.getSubjects();
            return subjects;
        } catch (Exception ex) {
            javax.swing.JOptionPane.showMessageDialog(this,"Si è verificato un errore accedendo al database.\nContattare l'amministratore di sistema.\n\nIl dettaglio dell'errore è:\n"+ex.getLocalizedMessage(),"Errore nell'accesso alla base di dati",javax.swing.JOptionPane.ERROR_MESSAGE);
            return null;
        }
    }

    /** get creators */
    private Vector getCreators() {
        try {
            //get data from database...
            Vector creators=core.getCreators();
            //... and adds null/description item
            creators.add(0,CREATORS_NULL_ITEM);
            return creators;
        } catch (Exception ex) {
            javax.swing.JOptionPane.showMessageDialog(this,"Si è verificato un errore accedendo al database.\nContattare l'amministratore di sistema.\n\nIl dettaglio dell'errore è:\n"+ex.getLocalizedMessage(),"Errore nell'accesso alla base di dati",javax.swing.JOptionPane.ERROR_MESSAGE);
            return null;
        }
    }

    /** get departments */
    private Vector getDepartments() {
        try {
            //get data from database...
            Vector departments=core.getDepartments();
            //... and remove administration department item
            departments.remove(ADMIN_DEPT);
            return departments;
        } catch (Exception ex) {
            javax.swing.JOptionPane.showMessageDialog(this,"Si è verificato un errore accedendo al database.\nContattare l'amministratore di sistema.\n\nIl dettaglio dell'errore è:\n"+ex.getLocalizedMessage(),"Errore nell'accesso alla base di dati",javax.swing.JOptionPane.ERROR_MESSAGE);
            return null;
        }
    }

    
    /** calls routine to acquire documents from a scanner */
    private void scanDocument() {
        //add this form as observer of core to be nofified when it changes
        core.addObserver(this);
        //create a new DogeScanWindow
        new DogeScanWindow(core).setVisible(true);
    }
    
    /** calls routine to add a new communication subject to the database */
    private void addNewSubject(javax.swing.JComboBox autoSelectCombo) {
        //shows input dialog in which the user can type the new item
        javax.swing.JOptionPane dialog=new javax.swing.JOptionPane();
        String newItem=dialog.showInputDialog("Inserire la denominazione del nuovo soggetto della comunicazione:");
        if (newItem==null){
            return;
        }
        try{
            //add new Item to the database
            core.addNewSubject(newItem);
            //refresh combo and get back new autoSelectCombo ID
            autoSelectCombo=refreshCombos(autoSelectCombo);
            //select newly inserted item
            autoSelectCombo.setSelectedItem(newItem);
        } catch (SQLException ex){
            if (ex.getSQLState().equals("23000")){
                showNotify("<html>Il soggetto inserito è già presente ed è stato selezionato automaticamente</html>",false);
                //select already inserted item
                autoSelectCombo.setSelectedItem(newItem);
            } else {
                javax.swing.JOptionPane.showMessageDialog(this,"Si è verificato un errore inserendo il nuovo soggetto nel database.\nSi potrebbero non avere permessi sufficienti per compiere quest'operazione\nContattare l'amministratore di sistema.\n\nIl dettaglio dell'errore è:\n"+ex.getLocalizedMessage(),"Errore nell'inserimento",javax.swing.JOptionPane.ERROR_MESSAGE);            
            }
        } catch (Exception ex){
            javax.swing.JOptionPane.showMessageDialog(this,"Si è verificato un errore inserendo il nuovo soggetto nel database.\nSi potrebbero non avere permessi sufficienti per compiere quest'operazione\nContattare l'amministratore di sistema.\n\nIl dettaglio dell'errore è:\n"+ex.getLocalizedMessage(),"Errore nell'inserimento",javax.swing.JOptionPane.ERROR_MESSAGE);
        }
    }
    
    /** show a notification in the top border of the frame
     * @param message: the notification message
     * @param errorMessage: true if the notification has to be an error message
     */
    private void showNotify(String message, boolean errorMessage) {
        //set different colors and icons according to the messsage type
        if (errorMessage){
            notifyLabel.setBackground(new java.awt.Color(238,0,0));
            notifyLabel.setForeground(new java.awt.Color(255,255,255));
            notifyLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/dogeUI/images/messagebox_critical.gif")));
        } else {
            notifyLabel.setBackground(new java.awt.Color(255, 255, 204));
            notifyLabel.setForeground(new java.awt.Color(0,0,0));
            notifyLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/dogeUI/images/messagebox_info.gif")));
        }
        //set notification text
        notifyLabel.setText(message);
        //make notification visible
        notifyLabel.setVisible(true);
    }
    
    /** hide the notification in the top border of the frame */
    private void hideNotify(){
        notifyLabel.setVisible(false);
    }

    /** utility method to check if fromCombo and toCombo contain a valid combination */
    private boolean fromToNotValid() {
        // true if both combo have a selected item and at least one of them is DOGE_OWNER
        return (fromCombo.getSelectedIndex()!=-1) && (toCombo.getSelectedIndex()!=-1) && 
                !((fromCombo.getSelectedItem().equals(DOGE_OWNER)) || (toCombo.getSelectedItem().equals(DOGE_OWNER))) ;
    }

    /** notify an invalid combination between fromCombo and toCombo */
    private void notifyFromToNotValid(boolean isNotValid) {
        //fromCombo.setForeground(Color.RED);
        //toCombo.setForeground(Color.RED);
        //set error message
        String errorText="<html>combinazione non valida tra i soggetti di provenienza e destinazione:<br>almeno uno dei due deve essere '<i>"+DOGE_OWNER+"</i>'</html>";
        fromErrorLabel.setText(errorText);
        toErrorLabel.setText(errorText);
        //show or hides error message according to parameter
        fromErrorLabel.setVisible(isNotValid);
        toErrorLabel.setVisible(isNotValid);
    }

    /** show or hide departmant combo according to user's department */
    private void setDepartmentCombo() {
        try {
            //obtain user's department'
            String department=core.getDepartment();
            //if the department is not ADMIN_DEPT hide the combo (and its related labels) because document's department is pre-defined...
            if (! department.equals(ADMIN_DEPT)){
                departmentLabel.setVisible(false);
                departmentLabel.setEnabled(false);
                departmentCombo.setVisible(false);
                departmentCombo.setEnabled(false);
                departmentErrorLabel.setVisible(false);
                departmentErrorLabel.setEnabled(false);
            } else {
                //... else show it allowing to set the document's department
                departmentCombo.setSelectedIndex(-1);
            }
        } catch (UserNotLoggedException ex) {
        }
    }

    /** call DogeCore to insert a new record in DoGe archive */
    private void insertRecord() {
        //check if inserted data is valid and/or complete
        if (insertedDataIsOK()){
            try {
                //send data to DogeCore for inserting
                String protocolAssigned=core.insertRecord(packData());
                //clean form to allow next insertion operation
                cleanUpForm();
                //show insertion successful notification with protocol number assigned to the document
                showNotify("<html>Inserimento effettuato. Il numero di protocollo assegnato al documento inserito è:<br><i>"+protocolAssigned+"</i></html>",false);
            } catch (Exception ex) {
                ex.printStackTrace();
                showNotify("<html>Si è verificato un errore durante l'inserimento.<br>Verificare la correttezza dei dati inseriti e riprovare. Se l'errore persiste contattare l'amministratore di sistema.",true);
            }
        } else {
            showNotify("<html>Impossibile proseguire con l'inserimento: alcuni campi contengono dati non ammessi o non sono stati riempiti tutti i campi obbligatori.<br>Verificare la correttezza dei dati inseriti e riprovare.",true);
        }
    }

    /** check if inserted data is complete and consistent */
    private boolean insertedDataIsOK() {
        //prepare strings
        String dateString=dateField.getText().trim();
        String expiresString=expiresField.getText().trim();
        try {
            return (core.binaryDataAcquired()) &&                                                                               //document is acquired...
                   (fromCombo.getSelectedIndex()!=-1) &&                                                                        //...from-subject is set...
                   (toCombo.getSelectedIndex()!=-1) &&                                                                          //...to-subject is set...
                   ((fromCombo.getSelectedItem().equals(DOGE_OWNER)) || (toCombo.getSelectedItem().equals(DOGE_OWNER))) &&      //...and their combination is valid...
                   ((getDate(dateString)!=null) && (dateString!="")) &&                                                         //...date is inserted and valid...
                   ((expiresString.equals("")) || (getDate(expiresString)!=null)) &&                                            //...if expiration is set it is valid...
                   (documentTypeCombo.getSelectedIndex()!=-1) &&                                                                //...document type is set...
                   ((! core.getDepartment().equals(ADMIN_DEPT)) || (departmentCombo.getSelectedIndex()!=-1));                   //...if department has to be selected manually it is set
        } catch (UserNotLoggedException ex) {
            return false;
        } 
    }

    /** store recorded data in a DogeRecord object */
    private DogeRecord packData() {
        DogeRecord record=new DogeRecord();
        //if creator is not null set creator
        String creator=(String)creatorCombo.getSelectedItem();
        if (! creator.equals(CREATORS_NULL_ITEM)){
            record.setCreator(creator);
        }
        //set from-subject
        record.setFromSubject((String)fromCombo.getSelectedItem());
        //set to-subject
        record.setToSubject((String)toCombo.getSelectedItem());
        //set date
        record.setDate(getDate(dateField.getText().trim()));
        //set expiration date
        record.setExpirationDate(getDate(expiresField.getText().trim()));
        //set document type
        record.setDocumentType((String)documentTypeCombo.getSelectedItem());
        try {
            //if department is to be selected set department
            if (core.getDepartment().equals(ADMIN_DEPT)){
                record.setDepartment((String)departmentCombo.getSelectedItem());
            }
        } catch (UserNotLoggedException ex) {}
        //set description
        record.setDescription(descriptionText.getText());
        return record;
    }

    /** (implementation of java.util.Observer) update scanned document status */
    public void update(Observable o, Object arg) {
        //get if the document has been inserted
        getScannedDataStatus();
        //delete observer (not used anymore...)
        core.deleteObserver(this);
    }

    /** ask core to determine if a document has been scanned and updates the UI */
    private void getScannedDataStatus() {
        //determine if binary data is present
        if (core.binaryDataAcquired()){
            //update UI reflecting document status
            documentStatusLabel.setText("inserito");
            documentErrorLabel.setVisible(false);
            documentButton.setText("Modifica...");
        } else {
            //update UI reflecting document status
            documentStatusLabel.setText("non inserito");
            documentErrorLabel.setVisible(true);
            documentButton.setText("Acquisisci...");
        }
    }

    /** resets insert form after a successful insertion */
    private void cleanUpForm() {
        //clean data stored in core 
        core.cleanUpData();
        //refresh document scanning status
        getScannedDataStatus();
        //sets all the fields to their null/default value for a new record
        creatorCombo.setSelectedItem(CREATORS_NULL_ITEM);
        fromCombo.setSelectedIndex(-1);
        toCombo.setSelectedIndex(-1);
        dateField.setText("");
        expiresField.setText("");
        documentTypeCombo.setSelectedIndex(-1);
        if (departmentCombo.isVisible()){
            departmentCombo.setSelectedIndex(-1);
        }
        descriptionText.setText(null);
        //refresh dates status
        checkDates();
        //assign focus to the Acquire button (first on the form)
        documentButton.grabFocus();
    }
    
    /** refreshes subject combos contents and returns new reference for @param autoSelectCombo */
    private javax.swing.JComboBox refreshCombos(javax.swing.JComboBox autoSelectCombo) {
        //get new subjects list
        this.subjects=getSubjects();
        String fromSubjectBackup=null;
        String toSubjectBackup=null;
        //determine if autoSelectCombo is fromCombo (used later to update autoSelectCombo when combos are substituted
        boolean autoSelectComboIsFrom=fromCombo.equals(autoSelectCombo);
        //backup current selections to restore them in the new combos
        if (fromCombo.getSelectedIndex()!=-1){
            fromSubjectBackup=(String) fromCombo.getSelectedItem();
        }
        if (toCombo.getSelectedIndex()!=-1){
            toSubjectBackup=(String) toCombo.getSelectedItem();
        }
        //remove old instances of combos
        insertPanel.remove(fromCombo);
        insertPanel.remove(toCombo);
        //create new combos
        initSubjectCombos();
        //restore selected items
        if (fromSubjectBackup!=null){
            fromCombo.setSelectedItem(fromSubjectBackup);
        }
        if (toSubjectBackup!=null){
            toCombo.setSelectedItem(toSubjectBackup);
        }
        //force frame to refresh
        validate();
        //return new autoSelectCombo (using boolean saved before)
        if (autoSelectComboIsFrom){
            return fromCombo;
        } else {
            return toCombo;
        }
    }

    /** initializes fromCombo and toCombo */
    private void initSubjectCombos() {
        //creates objects
        fromCombo = new javax.swing.JComboBox(subjects);
        toCombo = new javax.swing.JComboBox(subjects);
        java.awt.GridBagConstraints gridBagConstraints;

        //set font properties and event listeners for fromCombo
        fromCombo.setFont(new java.awt.Font("Dialog", 1, 14));
        fromCombo.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                fromComboItemStateChanged(evt);
            }
        });
        fromCombo.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                fromComboFocusLost(evt);
            }
        });

        //set size and position in the form layout for fromCombo
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        //insert fromCombo in the frame
        insertPanel.add(fromCombo, gridBagConstraints);
        
        //set font properties and event listeners for toCombo
        toCombo.setFont(new java.awt.Font("Dialog", 1, 14));
        toCombo.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                toComboItemStateChanged(evt);
            }
        });
            toCombo.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                toComboFocusLost(evt);
            }
        });
        
        //set size and position in the form layout for toCombo
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        //insert toCombo in the frame
        insertPanel.add(toCombo, gridBagConstraints);
    }
    
    /** returns frame default button to allow DogeMainWindow to set it as default */
    protected javax.swing.JButton getDefaultButton(){
        return confirmButton;
    }

    /** show a calendar for the specified TextField
     * @param calendarTextField: the textfield to which the calendar control is connected
     * @param calendarButton: the button that was pressed to call the calendar
     */
    private void showCalendar(javax.swing.JTextField calendarTextField, javax.swing.JButton calendarButton) {
        //saves textfield in which the return value will be written
        this.calendarTextField=calendarTextField;
        //resets dateSelected value to workaround popupmenu closing when month combo is clicked
        dateSelected=false;
        //if text in calendarTextField is a valid date set calendar to that date otherwise set the date to now
        Date date=getDate(calendarTextField.getText());
        if (date!=null){
            calendar=new com.toedter.calendar.JCalendar(date);            
        } else {
            calendar=new com.toedter.calendar.JCalendar();
        }
        //set properties and event listeners for the calendar:
        //fire an event even when clicking on an already selected day
        calendar.getDayChooser().setAlwaysFireDayProperty(true);
        //event handler for day change
        calendar.getDayChooser().addPropertyChangeListener("day",new java.beans.PropertyChangeListener() {
            public void propertyChange(PropertyChangeEvent evt) {
                calendarPropertyChange(calendar,evt);
                //a date has been selected
                dateSelected=true;
                //hide popup
                popup.setVisible(false);
            }
        });
        //add the calendar to the popupmenu, after removing other exixsting components in it
        popup.removeAll();
        popup.add(calendar);
        //show popup menu
        popup.show(calendarButton,0,calendarButton.getHeight());
    }

    /** return a date from a string, or null if the string is not a date */
    private Date getDate(String string) {
        SimpleDateFormat dateFormatter=(SimpleDateFormat)DateFormat.getDateInstance();
        //this way two-digit year ## is correctly interpreted as 19## (or 20##) and not erroneously interpreted as ## only
        dateFormatter.applyPattern("dd/MM/yy");
        //do not try to fix date errors (date has to be valid as it is written)
        dateFormatter.setLenient(false);
        try {
            //parse string to get date
            Date parsedDate=dateFormatter.parse(string);
            return parsedDate;
        } catch (ParseException ex) {
            //date is not valid
            return null;
        }
    }

    /** writes the date returned from the calendar widget in the related textbox */
    private void changeDate() {
        SimpleDateFormat dateFormatter=(SimpleDateFormat)DateFormat.getDateInstance();
        dateFormatter.applyPattern("dd/MM/yyyy");
        //write calendar-selected date in the corrensponding textbox
        calendarTextField.setText(dateFormatter.format( calendar.getDate() ) );
        //verify dates to hide (or show...) error notifications
        checkDates();
    }

    /** utility method to check if the dates in dateField and expiresField are valid and show a notification if that's not true */
    private void checkDates() {
        //get and prepare strings
        String dateString=dateField.getText().trim();
        String expiresString=expiresField.getText().trim();
        //prepare error message
        String dateNotValidErrorMessage="<html><center>la data inserita non è valida: digitare una data valida (in formato gg/mm/aaaa)<br>o cliccare il pulsante <i>Calendario...</i> e selezionarla</center></html>";
        //if date is not valid...
        if (getDate(dateString)==null){
            //... or better, is empty
            if (dateString.equals("")){
                //show date-not-inserted error
                dateErrorLabel.setText("<html><center>data non inserita: digitare una data (in formato gg/mm/aaaa)<br>o cliccare il pulsante <i>Calendario...</i> e selezionarla</center></html>");
                dateErrorLabel.setVisible(true);
            } else {
                //show date-not-valid error
                dateErrorLabel.setText(dateNotValidErrorMessage);
                dateErrorLabel.setVisible(true);                
            }
        } else {
            //there is no error
            dateErrorLabel.setVisible(false);                            
        }
        //if expiresDate is not valid...
        if ((getDate(expiresString)==null) && (! expiresString.equals(""))){
            //show date-not-valid error
            expiresErrorLabel.setText(dateNotValidErrorMessage);
            expiresErrorLabel.setVisible(true);                            
        } else {
            //there is no error
            expiresErrorLabel.setVisible(false);                            
        }
    }

    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel buttonsPanel;
    private javax.swing.JButton confirmButton;
    private javax.swing.JComboBox creatorCombo;
    private javax.swing.JLabel creatorLabel;
    private javax.swing.JButton dateCalendarButton;
    private javax.swing.JLabel dateErrorLabel;
    private javax.swing.JTextField dateField;
    private javax.swing.JLabel dateLabel;
    private javax.swing.JComboBox departmentCombo;
    private javax.swing.JLabel departmentErrorLabel;
    private javax.swing.JLabel departmentLabel;
    private javax.swing.JLabel descriptionLabel;
    private javax.swing.JTextArea descriptionText;
    private javax.swing.JButton documentButton;
    private javax.swing.JLabel documentErrorLabel;
    private javax.swing.JLabel documentLabel;
    private javax.swing.JLabel documentStatusLabel;
    private javax.swing.JComboBox documentTypeCombo;
    private javax.swing.JLabel documentTypeErrorLabel;
    private javax.swing.JLabel documentTypeLabel;
    private javax.swing.JButton expiresCalendarButton;
    private javax.swing.JLabel expiresErrorLabel;
    private javax.swing.JTextField expiresField;
    private javax.swing.JLabel expiresLabel;
    private javax.swing.JLabel fromErrorLabel;
    private javax.swing.JLabel fromLabel;
    private javax.swing.JButton fromNewButton;
    private javax.swing.JPanel insertPanel;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel notifyLabel;
    private javax.swing.JPopupMenu popup;
    private javax.swing.JLabel toErrorLabel;
    private javax.swing.JLabel toLabel;
    private javax.swing.JButton toNewButton;
    // End of variables declaration//GEN-END:variables
    private javax.swing.JComboBox fromCombo;
    private javax.swing.JComboBox toCombo;
    private com.toedter.calendar.JCalendar calendar;
    
    //core of this frame
    private DogeCore core;
    //communication subjects
    private Vector subjects;
    //some String constants...
    private static final String CREATORS_NULL_ITEM=" (nessuno)";
    private static final String DOGE_OWNER="-- Questa Azienda (Bell'Arte Tessile)";
    private static final String ADMIN_DEPT="Amministrazione";

    //boolean to workaround calendar closing when month combo is clicked
    private boolean dateSelected;
    //textfield in which insert the new date
    private javax.swing.JTextField calendarTextField;
}
